package org.gdstash.db;

import org.gdstash.util.GDMsgFormatter;
import org.gdstash.util.GDMsgLogger;

import java.sql.*;
import java.util.LinkedList;
import java.util.List;

public class DBLootTableAffixSetAlloc {
    private static final String TABLE_NAME = "GD_LOOTTABLE_AFFIXSET";
    private static final int ROW_TABLE_ID = 1;
    private static final int ROW_TYPE = 2;
    private static final int ROW_INDEX = 3;
    private static final int ROW_LEVEL_MIN = 4;
    private static final int ROW_LEVEL_MAX = 5;
    private static final int ROW_AFFIXSET_ID = 6;
    public static final int TYPE_PREFIX_NORMAL = 1;
    public static final int TYPE_SUFFIX_NORMAL = 2;
    public static final int TYPE_PREFIX_RARE = 3;
    public static final int TYPE_SUFFIX_RARE = 4;
    private String tableID;
    private int type;
    private int index;
    private int levelMin;
    private int levelMax;
    private String affixSetID;
    private DBAffixSet affixSet;

    public String getTableID() {
        return this.tableID;
    }

    public void setTableID(final String tableID) {
        this.tableID = tableID;
    }

    public int getAffixType() {
        return this.type;
    }

    public void setAffixType(final int type) {
        this.type = type;
    }

    public int getIndex() {
        return this.index;
    }

    public void setIndex(final int index) {
        this.index = index;
    }

    public int getMinLevel() {
        return this.levelMin;
    }

    public void setMinLevel(final int levelMin) {
        this.levelMin = levelMin;
    }

    public int getMaxLevel() {
        return this.levelMax;
    }

    public void setMaxLevel(final int levelMax) {
        this.levelMax = levelMax;
    }

    public String getAffixSetID() {
        return this.affixSetID;
    }

    public void setAffixSetID(final String affixSetID) {
        this.affixSetID = affixSetID;
    }

    public List<DBAffixSet.DBEntry> getAffixEntries() {
        if (this.affixSet == null) {
            return null;
        }
        return this.affixSet.getAffixEntries();
    }

    public static void createTable() throws SQLException {
        final String dropTable = "DROP TABLE GD_LOOTTABLE_AFFIXSET";
        final String createTable = "CREATE TABLE GD_LOOTTABLE_AFFIXSET (TABLE_ID    VARCHAR(256) NOT NULL, TYPE        INTEGER, INDEX       INTEGER, LEVEL_MIN   INTEGER, LEVEL_MAX   INTEGER, AFFIXSET_ID VARCHAR(256) NOT NULL, PRIMARY KEY (TABLE_ID, TYPE, INDEX))";
        try (final Connection conn = GDDBData.getConnection()) {
            final boolean auto = conn.getAutoCommit();
            conn.setAutoCommit(false);
            try (final Statement st = conn.createStatement()) {
                if (GDDBUtil.tableExists(conn, "GD_LOOTTABLE_AFFIXSET")) {
                    st.execute(dropTable);
                }
                st.execute(createTable);
                st.close();
                conn.commit();
            } catch (SQLException ex) {
                conn.rollback();
                final Object[] args = {"GD_LOOTTABLE_AFFIXSET"};
                final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_CREATE_TABLE", args);
                GDMsgLogger.addError(msg);
                throw ex;
            } finally {
                conn.setAutoCommit(auto);
            }
        }
    }

    public static void delete(final Connection conn, final String tableID) throws SQLException {
        final String deleteEntry = "DELETE FROM GD_LOOTTABLE_AFFIXSET WHERE TABLE_ID = ?";
        try (final PreparedStatement ps = conn.prepareStatement(deleteEntry)) {
            ps.setString(1, tableID);
            ps.executeUpdate();
            ps.close();
        } catch (SQLException ex) {
            throw ex;
        }
    }

    public static void insert(final Connection conn, final DBLootTable dbTable) throws SQLException {
        if (dbTable.getAffixSetAllocList() == null) {
            return;
        }
        if (dbTable.getAffixSetAllocList().isEmpty()) {
            return;
        }
        final String insert = "INSERT INTO GD_LOOTTABLE_AFFIXSET VALUES (?,?,?,?,?,?)";
        try (final PreparedStatement ps = conn.prepareStatement(insert)) {
            for (final DBLootTableAffixSetAlloc affixSet : dbTable.getAffixSetAllocList()) {
                if (affixSet.affixSetID != null) {
                    ps.setString(1, dbTable.getTableID());
                    ps.setInt(2, affixSet.type);
                    ps.setInt(3, affixSet.index);
                    ps.setInt(4, affixSet.levelMin);
                    ps.setInt(5, affixSet.levelMax);
                    ps.setString(6, affixSet.affixSetID);
                    ps.executeUpdate();
                    ps.clearParameters();
                }
            }
            ps.close();
            conn.commit();
        } catch (SQLException ex) {
            throw ex;
        }
    }

    public static List<DBLootTableAffixSetAlloc> getByTableID(final String tableID) {
        List<DBLootTableAffixSetAlloc> list = null;
        final String command = "SELECT * FROM GD_LOOTTABLE_AFFIXSET WHERE TABLE_ID = ?";
        try (final Connection conn = GDDBData.getConnection();
             final PreparedStatement ps = conn.prepareStatement(command)) {
            ps.setString(1, tableID);
            try (final ResultSet rs = ps.executeQuery()) {
                list = wrap(rs);
                conn.commit();
            } catch (SQLException ex) {
                throw ex;
            }
        } catch (SQLException ex2) {
            final Object[] args = {tableID, "GD_LOOTTABLE_AFFIXSET"};
            final String msg = GDMsgFormatter.format(GDMsgFormatter.rbMsg, "ERR_READ_TABLE_BY_ID", args);
            GDMsgLogger.addError(msg);
            GDMsgLogger.addError(ex2);
        }
        return list;
    }

    private static List<DBLootTableAffixSetAlloc> wrap(final ResultSet rs) throws SQLException {
        final LinkedList<DBLootTableAffixSetAlloc> list = new LinkedList<DBLootTableAffixSetAlloc>();
        while (rs.next()) {
            final DBLootTableAffixSetAlloc set = new DBLootTableAffixSetAlloc();
            set.tableID = rs.getString(1);
            set.type = rs.getInt(2);
            set.index = rs.getInt(3);
            set.levelMin = rs.getInt(4);
            set.levelMax = rs.getInt(5);
            set.affixSetID = rs.getString(6);
            if (set.affixSetID != null) {
                set.affixSet = DBAffixSet.get(set.affixSetID);
            }
            list.add(set);
        }
        return list;
    }
}
